/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */
package crawler.common;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.RandomAccessFile;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import java.nio.channels.FileChannel;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.HashMap;
import java.util.Map;
import java.util.logging.Level;
import org.apache.commons.io.FilenameUtils;
import org.apache.log4j.Logger;

/**
 *
 * @author LT
 */
public class FileUtil {

    private static final Logger logger = Logger.getLogger(FileUtil.class);
    private static final int BUFFER_SIZE = 4096;

    public static boolean downloadFile(String strURL, String pathToSave) {
        try {
            URL url = new URL(strURL);
            InputStream is = url.openStream();
            OutputStream os = new FileOutputStream(pathToSave);

            byte[] b = new byte[2048];
            int length;

            while ((length = is.read(b)) != -1) {
                os.write(b, 0, length);
            }
            is.close();
            os.close();
            Path path = Paths.get(pathToSave);
            String type = Files.probeContentType(path);
            System.out.println(type);
            return true;
        } catch (MalformedURLException | FileNotFoundException ex) {
            logger.error("DownloadFile: " + ex + ex.getMessage());
        } catch (IOException ex) {
            logger.error("DownloadFile: " + ex + ex.getMessage());
        }
        return false;
    }

    public static String download(String fileURL, String saveDir) {
        try {
            URL url = new URL(fileURL);
            HttpURLConnection httpConn = (HttpURLConnection) url.openConnection();
            int responseCode = httpConn.getResponseCode();

            // always check HTTP response code first
            if (responseCode == HttpURLConnection.HTTP_OK) {
                String fileName = "";
                String disposition = httpConn.getHeaderField("Content-Disposition");
                String contentType = httpConn.getContentType();
                int contentLength = httpConn.getContentLength();

                String realURL = httpConn.getURL().toString();
                
                if (disposition != null) {
                    // extracts file name from header field
                    int index = disposition.indexOf("filename=");
                    if (index > 0) {
                        fileName = disposition.substring(index + 10,
                                disposition.length() - 1);
                    }
                }
                else {
                    // extracts file name from URL
                    fileName = realURL.substring(realURL.lastIndexOf("/") + 1,
                            realURL.length());
                }
                if(fileName.isEmpty() || fileName.contains("?")){
                    fileName = fileName.replace(fileName.substring(fileName.lastIndexOf("?")),"");
                }
                String ext = getExtensionfromContentType(contentType);
                String currExt = FilenameUtils.getExtension(fileName);
                if(ext!=null && !ext.isEmpty() && (currExt==null || !currExt.equals(ext))){
                    fileName = fileName + "." + ext;
                }

                logger.info("Content-Type = " + contentType);
                logger.info("Content-Disposition = " + disposition);
                logger.info("Content-Length = " + contentLength);
                logger.info("fileName = " + fileName);

                // opens input stream from the HTTP connection
                InputStream inputStream = httpConn.getInputStream();
                String saveFilePath = saveDir + fileName;
                String nameBefore = saveFilePath;
                saveFilePath = generateFileNameIfDuplicate(saveFilePath);
                String nameAfter = saveFilePath;
                fileName = saveFilePath.substring(saveFilePath.lastIndexOf("/") + 1);

                // opens an output stream to save into file
                FileOutputStream outputStream = new FileOutputStream(saveFilePath);
                logger.info("filePath = " + saveFilePath);
                int bytesRead = -1;
                byte[] buffer = new byte[BUFFER_SIZE];
                while ((bytesRead = inputStream.read(buffer)) != -1) {
                    outputStream.write(buffer, 0, bytesRead);
                }

                outputStream.close();
                inputStream.close();
                logger.info("File downloaded");
                return fileName;
            } else {
                logger.error("No file to download. Server replied HTTP code: " + responseCode);
            }
            httpConn.disconnect();
        } catch (MalformedURLException ex) {
            logger.error("DownloadAnyFile: MalformedURLException" + ex + ex.getMessage());
        } catch (FileNotFoundException ex) {
            logger.error("DownloadAnyFile: FileNotFoundException" + ex + ex.getMessage());
        } catch (IOException ex) {
            logger.error("DownloadAnyFile: IOException" + ex + ex.getMessage());
        }
        return null;
    }

    public static String getExtensionfromContentType(String contentType) {
        String extension = "";
        switch (contentType) {
            case "image/jpeg":
                extension = "jpg";
                break;
            case "image/png":
                extension = "png";
                break;
        }
        return extension;
    }
    public static String generateFileNameIfDuplicate(String org){
        File f = new File(org);
        if(!f.exists() || f.isDirectory()){
            return org;
        }
        String res = org;
        String ext = FilenameUtils.getExtension(org);
        String bef = org.substring(0, org.lastIndexOf(ext)-1);
        int index = 0;
        while(f.exists() && !f.isDirectory()){
            index++;
            res = bef + "(" + index + ")." + ext;
            f = new File(res);
        }
        return res;
    }
    public static boolean isSameFile(String after, String before){
        return getFileSum(before) == getFileSum(after);
    }
    public static double getFileSum(String filePath){
        double sum = 0;
        try {
            File file;
            FileChannel channel;
            RandomAccessFile raf;
            int runs = 1;
            int iterations = 1;
            file = new File(filePath);
            channel = new FileInputStream(filePath).getChannel();
            raf = new RandomAccessFile(filePath, "r");
            
            HashMap<String, Double> times = new HashMap<String, Double>();
            times.put("file", 0.0);
            times.put("channel", 0.0);
            times.put("raf", 0.0);
            
            long start;
            for (int i = 0; i < runs; ++i) {
                long l = file.length();
                
                start = System.nanoTime();
                for (int j = 0; j < iterations; ++j)
                    if (l != file.length()) throw new Exception();
                times.put("file", times.get("file") + System.nanoTime() - start);
                
                start = System.nanoTime();
                for (int j = 0; j < iterations; ++j)
                    if (l != channel.size()) throw new Exception();
                times.put("channel", times.get("channel") + System.nanoTime() - start);
                
                start = System.nanoTime();
                for (int j = 0; j < iterations; ++j)
                    if (l != raf.length()) throw new Exception();
                times.put("raf", times.get("raf") + System.nanoTime() - start);
            }
            for (Map.Entry<String, Double> entry : times.entrySet()) {
                if(entry.getKey().equals("file")){
                    sum =  1e-3 * entry.getValue();
                }
 System.out.println(
            entry.getKey() + " sum: " + 1e-3 * entry.getValue() +
            ", per Iteration: " + (1e-3 * entry.getValue() / runs / iterations));
            }   } catch (FileNotFoundException ex) {
            java.util.logging.Logger.getLogger(FileUtil.class.getName()).log(Level.SEVERE, null, ex);
        } catch (Exception ex) {
            java.util.logging.Logger.getLogger(FileUtil.class.getName()).log(Level.SEVERE, null, ex);
        }
        return sum;
    }
}
